package com.ys.sboot.config.corecfg.exception;


import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Slf4j
@ControllerAdvice
public class DefaultExceptionHandler {

    /**
     * 普通拦截
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({
            MissingServletRequestParameterException.class,
            UnsatisfiedServletRequestParameterException.class,
            HttpRequestMethodNotSupportedException.class,
            HttpMessageNotReadableException.class,
            MissingServletRequestPartException.class,
            Exception.class
    })
    @ResponseBody
    public HttpMessage handleRequestException(Exception ex) {
        log.error("Exception: " + ex.getMessage(), ex);
        return HttpMessage.builder()
                .timestamp(new Date())
                .isSuccess(false)
                .code("500")
                .message(ex.getMessage())
                .build();
    }

    /**
     * post方式参数校验拦截
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public HttpMessage handleRequestValidException(MethodArgumentNotValidException ex) {
        StringBuilder sb = new StringBuilder();
        HashMap<String, String> map = new HashMap<>();
        sb.append(ex.getParameter().getMethod().getDeclaringClass().getName());//获取类名
        sb.append("--中的:方法").append(ex.getParameter().getMethod().getName());//获取方法名
        sb.append(",参数:【");
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        for (ObjectError error : allErrors) {
            FieldError error1 = (FieldError) error;
            map.put(error1.getField(), error1.getDefaultMessage());
            sb.append(error1.getField()).append(":").append(error1.getDefaultMessage());
        }
        sb.append("】校验失败:");
        log.error("hibernate校验----action类:{}", sb.toString());
        return HttpMessage.builder()
                .timestamp(new Date())
                .isSuccess(false)
                .code("400")
                .message(map)
                .build();
    }


    /**
     * Get拦截绑定参数异常校验(类里面的属性)
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public HttpMessage handleRequestBindValidException(BindException ex) {
        log.error("Exception: " + ex.getMessage(), ex);
        HashMap<String, String> map = new HashMap<>();
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        for (ObjectError error : allErrors) {
            FieldError error1 = (FieldError) error;
            map.put(error1.getField(), error1.getDefaultMessage());
        }
        return HttpMessage.builder()
                .timestamp(new Date())
                .isSuccess(false)
                .code("400")
                .message(map)
                .build();
    }


    /**
     * 认证相关的权限
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({AuthException.class,
            org.springframework.security.access.AccessDeniedException.class
    })
    @ResponseBody
    public HttpMessage handleAuthException(AuthException ex) {
        log.error("authException: {}", ex);
        return HttpMessage.builder()
                .timestamp(new Date())
                .isSuccess(false)
                .code(String.valueOf(ex.getCode()))
                .message(ex.getMessage())
                .build();
    }


}
